﻿using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;

public class CsCompiler
{
    public static bool CompileDirectoryToDll(
        string sourceDirectory,
        string outputDllPath,
        string? assemblyName = null)
    {
        // 获取所有.cs文件
        var csFiles = Directory.GetFiles(sourceDirectory, "*.cs", SearchOption.AllDirectories);
        if (csFiles.Length == 0) return false;

        // 解析语法树
        var syntaxTrees = new List<SyntaxTree>();
        foreach (var file in csFiles)
        {
            var sourceCode = File.ReadAllText(file);
            syntaxTrees.Add(CSharpSyntaxTree.ParseText(sourceCode));
        }

        // 获取必要引用
        var references = GetRequiredReferences();

        // 设置编译选项
        var compilationOptions = new CSharpCompilationOptions(
            OutputKind.DynamicallyLinkedLibrary,
            optimizationLevel: OptimizationLevel.Release,
            platform: Platform.AnyCpu);

        // 创建编译对象
        assemblyName = assemblyName ?? Path.GetFileNameWithoutExtension(outputDllPath);
        var compilation = CSharpCompilation.Create(
            assemblyName,
            syntaxTrees,
            references,
            compilationOptions);

        // 执行编译
        using var ms = new MemoryStream();
        EmitResult result = compilation.Emit(ms);

        // 处理编译结果
        if (result.Success)
        {
            File.WriteAllBytes(outputDllPath, ms.ToArray());
            return true;
        }

        // 输出错误信息
        var errors = result.Diagnostics
            .Where(d => d.Severity == DiagnosticSeverity.Error)
            .Select(d => $"{d.Id}: {d.GetMessage()}");

        Console.WriteLine("Compilation failed:");
        foreach (var error in errors)
        {
            Console.WriteLine(error);
        }

        return false;
    }

    public static bool CompileMethod2Dll(
        string sourceCode,
        string outputDllPath,
        string? assemblyName = null)
    {
        try
        {
            // 解析语法树
            var syntaxTrees = new List<SyntaxTree>();
            syntaxTrees.Add(CSharpSyntaxTree.ParseText(sourceCode));

            // 获取必要引用
            var references = GetRequiredReferences();

            // 设置编译选项
            var compilationOptions = new CSharpCompilationOptions(
                OutputKind.DynamicallyLinkedLibrary,
                optimizationLevel: OptimizationLevel.Debug, // 使用Debug模式获取更多信息
                platform: Platform.AnyCpu);

            // 创建编译对象
            assemblyName = assemblyName ?? Path.GetFileNameWithoutExtension(outputDllPath);
            var compilation = CSharpCompilation.Create(
                assemblyName,
                syntaxTrees,
                references,
                compilationOptions);

            // 执行编译
            using var ms = new MemoryStream();
            EmitResult result = compilation.Emit(ms);

            // 处理编译结果
            if (result.Success)
            {
                File.WriteAllBytes(outputDllPath, ms.ToArray());
                return true;
            }

            // 输出错误信息到控制台和文件
            var errors = result.Diagnostics
                .Where(d => d.Severity == DiagnosticSeverity.Error)
                .Select(d => $"{d.Id}: {d.GetMessage()} at {d.Location.GetLineSpan()}")
                .ToList();

            var errorText = string.Join("\n", errors);
            
            // 保存错误信息到文件
            var errorLogPath = Path.ChangeExtension(outputDllPath, ".errors.txt");
            File.WriteAllText(errorLogPath, errorText);

            Console.WriteLine("Compilation failed:");
            foreach (var error in errors)
            {
                Console.WriteLine(error);
            }

            return false;
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Compiler exception: {ex.Message}");
            return false;
        }
    }
    private static List<PortableExecutableReference> GetRequiredReferences()
    {
        var references = new List<PortableExecutableReference>();

        // 添加核心程序集引用
        var coreAssemblyPath = typeof(object).Assembly.Location;
        var coreAssemblyDir = Path.GetDirectoryName(coreAssemblyPath)!;

        // 基本运行时程序集
        var essentialAssemblies = new[]
        {
            "System.Private.CoreLib.dll",
            "System.Runtime.dll",
            "System.Console.dll",
            "netstandard.dll",
            "System.dll",
            "KrasDD.dll"
        };

        foreach (var asm in essentialAssemblies)
        {
            var path = Path.Combine(coreAssemblyDir, asm);
            if (File.Exists(path))
            {
                references.Add(MetadataReference.CreateFromFile(path));
            }
        }

        // 添加当前加载的所有用户程序集
        foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
        {
            if (!assembly.IsDynamic && !string.IsNullOrEmpty(assembly.Location))
            {
                references.Add(MetadataReference.CreateFromFile(assembly.Location));
            }
        }

        return references;
    }
}
